/*
 *
 *  *    Copyright © OpenAtom Foundation.
 *  *
 *  *    Licensed under the Apache License, Version 2.0 (the "License");
 *  *    you may not use this file except in compliance with the License.
 *  *    You may obtain a copy of the License at
 *  *
 *  *         http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  *    Unless required by applicable law or agreed to in writing, software
 *  *    distributed under the License is distributed on an "AS IS" BASIS,
 *  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *    See the License for the specific language governing permissions and
 *  *    limitations under the License.
 *
 */

package com.inspur.edp.commonmodel.engine.api.data;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.GspFieldCollection;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateSerUtil;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;
import java.io.IOException;
import java.util.Date;
import java.util.Map;

public class AssoInfoJsonSerializer extends JsonSerializer<AssociationInfo> {

  private static ObjectMapper defaultMapper = new ObjectMapper();

  @Override
  public void serialize(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
      SerializerProvider serializerProvider) throws IOException {
    if (associationInfo == null) {
      jsonGenerator.writeNull();
    } else {
      jsonGenerator.writeStartObject();
      if (associationInfo.getAssociation() == null) {
        serializeCore(associationInfo, jsonGenerator, serializerProvider);
      } else {
        serializeCoreWithAsso(associationInfo, jsonGenerator, serializerProvider);
      }
      jsonGenerator.writeEndObject();
    }
  }

  private void serializeCore(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
      SerializerProvider serializerProvider) throws IOException {
    for (Map.Entry<String, Object> pair : associationInfo.getValues().entrySet()) {
      jsonGenerator.writeFieldName(StringUtils.toCamelCase(pair.getKey()));
      Object value = pair.getValue();
      if (value instanceof Date) {
        if (value == null) {
          jsonGenerator.writeNull();
        } else {
          jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDateTime((Date) value));
        }
      } else if (value instanceof ICefData) {
        jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
      } else {
        serializerProvider.defaultSerializeValue(pair.getValue(), jsonGenerator);
      }
    }
  }

  private void serializeCoreWithAsso(AssociationInfo associationInfo, JsonGenerator jsonGenerator,
      SerializerProvider serializerProvider) throws IOException {
    GspAssociation gspAssociation = associationInfo.getAssociation();
    GspFieldCollection fieldCollection = gspAssociation.getRefElementCollection();
    if (gspAssociation.getBelongElement() != null) {
      jsonGenerator
          .writeFieldName(StringUtils.toCamelCase(gspAssociation.getBelongElement().getLabelID()));
      Object value = associationInfo.getValue(gspAssociation.getBelongElement().getLabelID());
      serializerProvider.defaultSerializeValue(value, jsonGenerator);
    }
    if (fieldCollection != null && !fieldCollection.isEmpty()) {
      for (IGspCommonField field : fieldCollection) {
        if (gspAssociation.getBelongElement() != null && field.getLabelID()
            .equalsIgnoreCase(gspAssociation.getBelongElement().getLabelID())) {
          continue;
        }
        jsonGenerator.writeFieldName(StringUtils.toCamelCase(field.getLabelID()));
        Object value = associationInfo.getValue(field.getLabelID());
        if (value == null) {
          jsonGenerator.writeNull();
        } else if(value instanceof Date) {
          switch (field.getMDataType()) {
            case DateTime:
              jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDateTime((Date) value));
              break;
            case Date:
              jsonGenerator.writeString(BefDateSerUtil.getInstance().writeDate((Date) value));
              break;
            default:
              serializerProvider.defaultSerializeValue(value, jsonGenerator);
              break;
          }
        } else if (value instanceof ICefData) {
          jsonGenerator.writeRawValue(defaultMapper.writeValueAsString(value));
        } else {
          serializerProvider.defaultSerializeValue(value, jsonGenerator);
        }
      }
    }
  }
}
